package cn.core.dict.service.impl;

import cn.core.dict.eo.Dict;
import cn.core.dict.eo.DictValue;
import cn.core.dict.mapper.DictMapper;
import cn.core.dict.mapper.DictValueMapper;
import cn.core.dict.qo.DictQO;
import cn.core.dict.qo.DictValueQO;
import cn.core.dict.service.intf.IDictService;
import cn.core.dict.vo.DictAndValueVO;
import cn.core.dict.vo.DictVO;
import cn.core.dict.vo.DictValueVO;
import cn.core.tool.exception.CoreException;
import cn.core.tool.util.CoreTool;
import cn.core.tool.util.CoreTree;
import cn.core.tool.util.Paging;
import cn.core.tool.util.Param;
import lombok.extern.log4j.Log4j2;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;

/**
 * 数据字典 服务实现
 */
@Log4j2
@Primary
@Service
public class DictServiceImpl implements IDictService {

  @Resource
  private DictMapper dictMapper;

  @Resource
  private DictValueMapper dictValueMapper;

  @Override
  @Transactional(propagation = Propagation.REQUIRED, readOnly = false)
  public Dict save(Dict eo) throws Exception {
    try {
      if (CoreTool.isNullEo(eo)) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      eo.setId(CoreTool.getUUID32());
      dictMapper.save(eo);
      return eo;
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  @Override
  @Transactional(propagation = Propagation.REQUIRED, readOnly = false)
  public Collection<Dict> saveBatch(Collection<Dict> eos) throws Exception {
    try {
      if (CoreTool.isEmpty(eos)) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      for (Dict eo : eos) {
        if (CoreTool.isNullEo(eo)) {
          throw new CoreException(CoreException.E_PARAM_ERR);
        }
        eo.setId(CoreTool.getUUID32());
      }
      dictMapper.saveBatch(new Paging<>(), eos);
      return eos;
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  @Override
  @Transactional(propagation = Propagation.REQUIRED, readOnly = false)
  public Dict update(Dict eo) throws Exception {
    try {
      if (CoreTool.isNullEo(eo) || CoreTool.isNullStr(eo.getId())) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      Dict oeo = dictMapper.pk(new DictQO().setId(eo.getId()));
      if (CoreTool.isNullEo(oeo)) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
//      if (eo.getVersions() != null ? !eo.getVersions().equals(oeo.getVersions()) : oeo.getVersions() != null ? true : false) {
//        throw new CoreException(CoreException.E_VERSIONS_ERR);
//      }
      dictMapper.update(eo);
      return eo;
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  @Override
  @Transactional(propagation = Propagation.REQUIRED, readOnly = false)
  public Collection<Dict> updateBatch(Collection<Dict> eos) throws Exception {
    try {
      if (CoreTool.isEmpty(eos)) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      for (Dict eo : eos) {
        if (CoreTool.isNullEo(eo) || CoreTool.isNullStr(eo.getId())) {
          throw new CoreException(CoreException.E_PARAM_ERR);
        }
        Dict oeo = dictMapper.pk(new DictQO().setId(eo.getId()));
        if (CoreTool.isNullEo(oeo)) {
          throw new CoreException(CoreException.E_PARAM_ERR);
        }
//        if (eo.getVersions() != null ? !eo.getVersions().equals(oeo.getVersions()) : oeo.getVersions() != null ? true : false) {
//          throw new CoreException(CoreException.E_VERSIONS_ERR);
//        }
      }
      dictMapper.updateBatch(new Paging<>(), eos);
      return eos;
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  @Override
  @Transactional(propagation = Propagation.REQUIRED, readOnly = false)
  public void remove(Dict eo) throws Exception {
    try {
      if (CoreTool.isNullEo(eo) || CoreTool.isNullStr(eo.getId())) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      dictMapper.remove(eo);
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  @Override
  @Transactional(propagation = Propagation.REQUIRED, readOnly = false)
  public void removeBatch(Collection<Dict> eos) throws Exception {
    try {
      if (CoreTool.isEmpty(eos)) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      LinkedHashSet<String> fkidAndIn = new LinkedHashSet<>();
      for (Dict eo : eos) {
        if (CoreTool.isNullEo(eo) || CoreTool.isNullStr(eo.getId())) {
          throw new CoreException(CoreException.E_PARAM_ERR);
        }
        fkidAndIn.add(eo.getId());
      }
      if (CoreTool.isNotEmpty(fkidAndIn)) {
        dictValueMapper.removeQuery(new DictValueQO().setFkidAndIn(fkidAndIn));
      }
      dictMapper.removeBatch(eos);
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  @Override
  public Long count(DictQO qo) throws Exception {
    try {
      return dictMapper.count(qo);
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  @Override
  public Dict pk(DictQO qo) throws Exception {
    try {
      if (CoreTool.isNullEo(qo) || CoreTool.isNullStr(qo.getId())) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      return dictMapper.pk(qo);
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  @Override
  public Collection<Dict> query(DictQO qo) throws Exception {
    try {
      return dictMapper.query(qo);
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  @Override
  public Paging<Dict> paging(Param<DictQO> param) throws Exception {
    try {
      if (CoreTool.isNullEo(param)) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      if (param.getPage() < 1 || param.getRows() < 1) {
        throw new CoreException(CoreException.E_PAGING_PARAM_ERR);
      }
      Paging<Dict> paging = new Paging<>(param);
      if (CoreTool.isEmpty(param.getData()) || CoreTool.isNullEo(param.get())) {
        Long count = dictMapper.count(null);
        paging.setCount(count);
        if (count > 0) {
          if (count <= paging.getOffset()) {
            throw new CoreException(CoreException.E_PAGING_PARAM_ERR);
          }
          paging.setData(dictMapper.paging(paging, null));
        }
      } else {
        Long count = dictMapper.count(param.get());
        paging.setCount(count);
        if (count > 0) {
          if (count <= paging.getOffset()) {
            throw new CoreException(CoreException.E_PAGING_PARAM_ERR);
          }
          paging.setData(dictMapper.paging(paging, param.get()));
        }
      }
      return paging;
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  @Override
  public Long countVo(DictQO qo) throws Exception {
    try {
      return dictMapper.countVo(qo);
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  @Override
  public DictVO pkVo(DictQO qo) throws Exception {
    try {
      if (CoreTool.isNullEo(qo) || CoreTool.isNullStr(qo.getId())) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      return dictMapper.pkVo(qo);
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  @Override
  public Collection<DictVO> queryVo(DictQO qo) throws Exception {
    try {
      return dictMapper.queryVo(qo);
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  @Override
  public Paging<DictVO> pagingVo(Param<DictQO> param) throws Exception {
    try {
      if (CoreTool.isNullEo(param)) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      if (param.getPage() < 1 || param.getRows() < 1) {
        throw new CoreException(CoreException.E_PAGING_PARAM_ERR);
      }
      Paging<DictVO> paging = new Paging<>(param);
      if (CoreTool.isEmpty(param.getData()) || CoreTool.isNullEo(param.get())) {
        Long count = dictMapper.countVo(null);
        paging.setCount(count);
        if (count > 0) {
          if (count <= paging.getOffset()) {
            throw new CoreException(CoreException.E_PAGING_PARAM_ERR);
          }
          paging.setData(dictMapper.pagingVo(paging, null));
        }
      } else {
        Long count = dictMapper.countVo(param.get());
        paging.setCount(count);
        if (count > 0) {
          if (count <= paging.getOffset()) {
            throw new CoreException(CoreException.E_PAGING_PARAM_ERR);
          }
          paging.setData(dictMapper.pagingVo(paging, param.get()));
        }
      }
      return paging;
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  @Override
  public DictAndValueVO getDictAndValueByDictKey(DictQO qo) throws Exception {
    try {
      if (CoreTool.isNullStr(qo.getDictKey())) {
        throw new CoreException("参数错误，数据字典标识为空！");
      }
      DictAndValueVO rDictAndValueVO = new DictAndValueVO().setDictValue(Collections.emptyList());
      Collection<Dict> rDictSet = dictMapper.query(qo);
      if (CoreTool.isNotEmpty(rDictSet)) {
        rDictAndValueVO.setDict(rDictSet.iterator().next());
        rDictAndValueVO.setDictValue(dictValueMapper.query(
            new DictValueQO()
                .setFkid(rDictAndValueVO.getDict().getId())
                .setWeightOrderAsc("y")));
        if ("tree".equals(rDictAndValueVO.getDict().getValueType()) && "TreeSelect".equals(rDictAndValueVO.getDict().getAssemblyType())) {
          CoreTree<?> tree = null;
          Collection<CoreTree<?>> treeSet = new ArrayList<>();
          for (DictValue eo : rDictAndValueVO.getDictValue()) {
            treeSet.add(new CoreTree<DictValue>(eo)
                .setId(eo.getId())
                .setKey(eo.getId())
                .setName(eo.getDisplayName())
                .setTkey(eo.getValueType())
                .setTitle(eo.getDisplayName() + " - [" + eo.getValueTypeName() + "]")
                .setValue(eo.getCodeName())
                .setPid(eo.getPid()));
          }
          tree = CoreTool.toTree(treeSet, true);
          rDictAndValueVO.setDictValueTreeData(tree);
        }
      }
      return rDictAndValueVO;
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  @Override
  public LinkedHashMap<String, LinkedHashMap<String, String>> getAllDictValueMapInfo() throws Exception {
    try {
      LinkedHashMap<String, LinkedHashMap<String, String>> allDictValueMapInfo = new LinkedHashMap<>();
      Collection<DictValueVO> rDictValueVOSet = dictValueMapper.queryVo(new DictValueQO().setDictKeyAsc("y"));
      if (CoreTool.isNotEmpty(rDictValueVOSet)) {
        for (DictValueVO eo : rDictValueVOSet) {
          if (allDictValueMapInfo.containsKey(eo.getDictKey())) {
            allDictValueMapInfo.get(eo.getDictKey()).put(eo.getCodeName(), eo.getDisplayName());
          } else {
            allDictValueMapInfo.put(eo.getDictKey(), new LinkedHashMap<String, String>());
            allDictValueMapInfo.get(eo.getDictKey()).put(eo.getCodeName(), eo.getDisplayName());
          }
        }
      }
      return allDictValueMapInfo;
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

}
